﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mads.CoreDomain;
using Mads.CoreDomain.Enumerations;

namespace Mads.WcfService
{
  internal class ClientUser
  {
    private int attempts = 0;
    private DateTime lastLogin = DateTime.Now;
    private int sumResult = 0;
    public bool IsBot()
    {
      attempts ++;
      bool isBot = attempts >= 3 && (DateTime.Now - lastLogin).TotalMinutes < 15;
      lastLogin = DateTime.Now;
      return isBot;
    }
    public void LoginSucceed()
    {
      attempts = 0;
    }
    public string GetInfoToCheckBot()
    {
      int a = (new Random(100)).Next();
      int b = (new Random(100)).Next();
      sumResult = a + b;
      return a.ToString() + " + " + b.ToString();
    }
    public bool CheckBot(int s)
    {
      return sumResult == s;
    }
    protected User user;
    protected TrainBaseConnector trainBaseConnector;

    protected bool BuyTicket(FreeTicket freeTicket, Station departure,
      Station arrival, string name, string docNumber, TicketState state)
    {
      Ticket ticket = trainBaseConnector.GetTicketWithInfo(freeTicket.ID);
      TicketOwner owner = new TicketOwner(name, docNumber);
      // check that this ticket exists and is not bought by someone else
      if (ticket == null ||
          (ticket.Owner != null && !owner.Equals(ticket.Owner)))
      {
        return false;
      }

      trainBaseConnector.Add(ticket.Owner = owner);
      ticket.State = state;
      ticket.Bought = DateTime.UtcNow;
      ticket.LogicalID = ticket.ID.ToString();
      //ticket.Buyer = user;

      //remember ticket old borders to add new tickets afterwards
      RouteStop start = ticket.StartStation;
      RouteStop end = ticket.EndStation;

      ticket.StartStation =
        trainBaseConnector.GetRouteStop(ticket.Seat.Race.Route, departure);
      ticket.EndStation =
        trainBaseConnector.GetRouteStop(ticket.Seat.Race.Route, arrival);

      if (!trainBaseConnector.Persist(ticket))
      {
        return false;
      }
      if (start.StationNumber < ticket.StartStation.StationNumber)
      {
        trainBaseConnector.Add(new Ticket(
          ticket.Seat, start, ticket.StartStation, TicketState.Free));
      }
      if (end.StationNumber > ticket.EndStation.StationNumber)
      {
        trainBaseConnector.Add(new Ticket(
          ticket.Seat, ticket.EndStation, end, TicketState.Free));
      }

      return true;
    }

    public ClientUser(TrainBaseConnector trainBaseConnector, User user)
    {
      this.user = user;
      this.trainBaseConnector = trainBaseConnector;
    }

    public virtual bool BuyTicket(FreeTicket freeTicket, Station departure,
      Station arrival, string name, string docNumber)
    {
      return BuyTicket(
        freeTicket, departure, arrival, name, docNumber, TicketState.Pending);
    }

    public ClientUser(TrainBaseConnector trainBaseConnector)
    {
      this.trainBaseConnector = trainBaseConnector;
    }

    public IEnumerable<FreeTicket> GetTickets(
      DateTime startTime, DateTime endTime,
      Station departureStation, Station arrivalStation)
    {
      TicketPrice price =
        trainBaseConnector.GetTicketPrice(departureStation, arrivalStation);

      var tickets = new List<FreeTicket>(
        trainBaseConnector.GetTickets(
          startTime, endTime, departureStation, arrivalStation));

      //TODO - gather collection of season prices in a single batch
      Dictionary<DateTime, float> seasonPrices =
        tickets.Select(x => x.DepartureTime).Distinct()
          .ToDictionary(
            date => date,
            date => trainBaseConnector.GetSeasonPrice(date).PriceMultiplier);

      foreach (FreeTicket ticket in tickets)
      {
        ticket.Price = price.Price
          * seasonPrices[ticket.DepartureTime]
          * ticket.Type.PriceMultiplier;
      }

      return tickets;
      //return tickets
      //  .Select(x => new FreeTicket(
      //    x.Seat.Number,
      //    x.Seat.Race.Departure + x.StartStation.DepartureTime.Value,
      //    x.Seat.Race.Departure + x.StartStation.ArrivalTime.Value,
      //    x.Seat.Car.CarType,
      //    price.Price
      //      * seasonPrices[x.Seat.Race.Departure]
      //      * x.Seat.Car.CarType.PriceMultiplier,
      //    x.Seat.Car.Number,
      //    x.Seat.Number));

    }

    /// <summary>
    /// Tries to buy ticket.
    /// If given stations don't match ticket's border station,
    /// ticket is "shortened"
    /// </summary>
    /// <returns>Whether the operation was successful.</returns>
    public bool BuyTicket(
      Ticket freeTicket, Station departureStation, Station arrivalStation)
    {
      return false;
    }

    public Ticket GetTicketByNumber(string logicalID)
    {
      return trainBaseConnector.GetTicketByNumber(logicalID);
    }
  }
}